package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.cart.model.CartInfo;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.common.util.SnowFlake;
import com.atguigu.gmall.enums.model.OrderStatus;
import com.atguigu.gmall.enums.model.PaymentStatus;
import com.atguigu.gmall.enums.model.PaymentWay;
import com.atguigu.gmall.enums.model.ProcessStatus;
import com.atguigu.gmall.order.model.OrderDetail;
import com.atguigu.gmall.order.model.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderDetailService;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.product.model.SkuInfo;
import com.atguigu.gmall.rabbit.config.MqConst;
import com.atguigu.gmall.rabbit.service.RabbitService;
import com.atguigu.gmall.user.client.UserFeignClient;
import com.atguigu.gmall.user.model.UserAddress;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import springfox.documentation.spring.web.json.Json;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单表 订单表 业务实现类
 *
 * @author atguigu
 * @since 2023-09-15
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private SnowFlake snowFlake;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RabbitService rabbitService;

    /**
     * 获取当前登录用户订单确认页相关数据汇总
     * ${userAddressList} 用户收件地址列表
     * ${detailArrayList}  商品清单列表
     * ${totalNum}  商品数量
     * ${totalAmount} 订单总金额
     * ${tradeNo} 订单渲染本次流水号
     *
     * @return
     */
    @Override
    public Map<String, Object> orderTradeData(String userId) {
        ConcurrentHashMap<String, Object> mapResult = new ConcurrentHashMap<>();

        //1.远程调用用户微服务获取当前用户收件地址列表-封装收件地址
        CompletableFuture<Void> userAddressListCompletableFuture = CompletableFuture.runAsync(() -> {
            List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(Long.valueOf(userId));
            mapResult.put("userAddressList", userAddressList);
        }, threadPoolExecutor);

        //2.远程调用购物车微服务获取用户选中购物车商品列表-封装商品明细
        CompletableFuture<Void> orderDetailCompletableFuture = CompletableFuture.runAsync(() -> {
            List<CartInfo> cartInfoList = cartFeignClient.getCartCheckedList(Long.valueOf(userId));
            //将集合泛型从购物车改为订单明细
            if (!CollectionUtils.isEmpty(cartInfoList)) {
                List<OrderDetail> orderDetailList = cartInfoList.stream().map(cartInfo -> {
                    OrderDetail orderDetail = new OrderDetail();
                    BeanUtils.copyProperties(cartInfo, orderDetail);
                    orderDetail.setOrderPrice(cartInfo.getSkuPrice());
                    return orderDetail;
                }).collect(Collectors.toList());
                mapResult.put("detailArrayList", orderDetailList);
                //3.封装商品总金额
                OrderInfo orderInfo = new OrderInfo();
                orderInfo.setOrderDetailList(orderDetailList);
                orderInfo.sumTotalAmount();
                mapResult.put("totalAmount", orderInfo.getTotalAmount());

                //4.封装商品数量
                mapResult.put("totalNum", orderDetailList.size());
            }
        }, threadPoolExecutor);


        //5.TODO 渲染订单确认页面生成随机流水号，解决浏览器回退导致订单重复提交
        String tradeNo = this.generateTradeNo(userId);
        mapResult.put("tradeNo", tradeNo);

        CompletableFuture.allOf(userAddressListCompletableFuture, orderDetailCompletableFuture).join();
        return mapResult;
    }

    /**
     * 提交商城订单
     *
     * @param orderInfo
     * @param tradeNo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long submitOrder(OrderInfo orderInfo, String tradeNo) {
        //1.验证用户是否通过浏览器回退进行重复提交订单
        //1.1 获取Redis中存放流水号 跟用户提交比较
        //Boolean flag = this.checkTradeNo(orderInfo.getUserId().toString(), tradeNo);
        //if (!flag) {
        //    throw new RuntimeException("请勿重复提交订单，请尝试重试");
        //}
        //1.2 验证通过，将Redis中存放流水号删除
        //this.deleteTradeNo(orderInfo.getUserId().toString());

        //1.3 采用Lua脚本保证判断删除流水号原子性 KEYS[1]:流水号Key    ARGV[1]：用户流水号
        String userTradeKey = RedisConst.USER_KEY_PREFIX + orderInfo.getUserId() + ":tradeNo";
        String scriptText = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(scriptText);
        redisScript.setResultType(Long.class);
        Long flag = (Long) redisTemplate.execute(redisScript, Arrays.asList(userTradeKey), tradeNo);
        if (flag == 0) {
            throw new RuntimeException("请勿重复提交订单，请尝试重试");
        }

        //2.（远程调用商品服务）验证商品上下架状态
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if (CollectionUtils.isEmpty(orderDetailList)) {
            throw new RuntimeException(ResultCodeEnum.SECKILL_ILLEGAL.getMessage());
        }
        //2.1 遍历订单中包含商品明细列表
        String cartKey = RedisConst.USER_KEY_PREFIX + orderInfo.getUserId() + RedisConst.USER_CART_KEY_SUFFIX;
        BoundHashOperations<String, String, CartInfo> cartHashOps = redisTemplate.boundHashOps(cartKey);

        //6. 采用异步任务进行优化
        List<CompletableFuture> allCompletableFutures = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            String cartHashKey = orderDetail.getSkuId().toString();
            //2.2 根据商品ID查询商品信息 判断商品状态
            CompletableFuture<Void> skuStatusCompletableFuture = CompletableFuture.runAsync(() -> {
                SkuInfo skuInfo = productFeignClient.getSkuInfo(orderDetail.getSkuId());
                if (skuInfo == null || skuInfo.getIsSale() == 0) {
                    //2.3 将用户购物车中商品删除(也可以更新缓存中购物车商品状态-前端判断变成灰色) 方式一：直接操作购物车Redis（违背微服务单一职责原则） 方式二：远程调用购物车微服务Feign接口
                    cartHashOps.delete(cartHashKey);
                    throw new RuntimeException("购买商品：" + orderDetail.getSkuId() + " 不存在,或者商品下架！");
                }
            }, threadPoolExecutor);

            //3.（远程调用商品服务）验证商品价格
            CompletableFuture<Void> priceCompletableFuture = CompletableFuture.runAsync(() -> {
                BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
                if (orderDetail.getOrderPrice().compareTo(skuPrice) != 0) {
                    CartInfo cartInfo = cartHashOps.get(cartHashKey);
                    if (cartInfo != null) {
                        //更新购物车商品价格
                        cartInfo.setSkuPrice(skuPrice);
                        cartHashOps.put(cartHashKey, cartInfo);
                    }
                    throw new RuntimeException("购买商品：" + orderDetail.getSkuId() + " 价格发生变化！");
                }
            }, threadPoolExecutor);

            //4.（远程调用仓储服务）验证商品库存
            CompletableFuture<Void> stockCompletableFuture = CompletableFuture.runAsync(() -> {
                boolean hashStock = this.checkSkuStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                if (!hashStock) {
                    throw new RuntimeException("购买商品：" + orderDetail.getSkuId() + " 库存不足！");
                }
            }, threadPoolExecutor);

            //6.1 将当前商品三个异步任务进行收集
            allCompletableFutures.add(skuStatusCompletableFuture);
            allCompletableFutures.add(priceCompletableFuture);
            allCompletableFutures.add(stockCompletableFuture);
        }

        //6.2 组合异步任务
        CompletableFuture.allOf(allCompletableFutures.toArray(new CompletableFuture[allCompletableFutures.size()])).join();

        //5.保存订单以及订单明细(核心业务)
        Long orderId = this.saveOrderInfo(orderInfo, "1");

        //6.TODO 商城订单采用延迟消息方式-检查订单&关闭订单
        //TODO 测试设置为20秒延迟 真实延迟时间跟订单设置过期时间 动态计算出来
        Date expireTime = orderInfo.getExpireTime();
        Date now = new Date();
        Long ttl = (expireTime.getTime() - now.getTime()) / 1000;
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL, MqConst.ROUTING_ORDER_CANCEL, orderId, 20);

        //TODO 订单提交后购物车数据清理，开发阶段不清理
        return orderId;
    }


    /**
     * 保存订单及订单明细
     *
     * @param orderInfo
     * @param orderType 订单类型 1：商城订单 2：秒杀订单
     * @return
     */
    @Override
    public Long saveOrderInfo(OrderInfo orderInfo, String orderType) {
        //1.构建订单对象，保存订单
        //1.1 订单状态(待支付状态)

        orderInfo.setOrderStatus(ProcessStatus.UNPAID.name());
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());

        //1.2 订单业务相关时间
        Date now = new Date();
        orderInfo.setOperateTime(now);
        //设置取消订单 一小时未支付订单，将订单关闭(基于延迟消息实现延迟关单)
        Calendar calendar = Calendar.getInstance();
        if ("1".equals(orderType)) {
            calendar.add(Calendar.HOUR, 1);
            //1.3 生成订单唯一编号（全局唯一） 形式：SPH+年月日+雪花算法
            String today = DateUtil.formatDate(now).replaceAll("-", "");
            String outTradeNo = "SPH" + today + snowFlake.nextId();
            orderInfo.setOutTradeNo(outTradeNo);
        } else if ("2".equals(orderType)) {
            calendar.add(Calendar.MINUTE, 5);
        }
        orderInfo.setExpireTime(calendar.getTime());
        //设置订单允许退货 7天内
        calendar.add(Calendar.DAY_OF_WEEK, 7);
        orderInfo.setRefundableTime(calendar.getTime());


        //1.4 其他普通字段
        orderInfo.sumTotalAmount();

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if (!CollectionUtils.isEmpty(orderDetailList)) {
            String skuNames = orderDetailList.stream().map(OrderDetail::getSkuName).collect(Collectors.joining(","));
            if (skuNames.length() > 100) {
                skuNames = skuNames.substring(0, 100);
            }
            orderInfo.setTradeBody(skuNames);
            orderInfo.setImgUrl(orderDetailList.get(0).getImgUrl());
        }
        this.save(orderInfo);
        Long orderId = orderInfo.getId();
        //2.构建订单明细集合，批量保存订单明细
        if (!CollectionUtils.isEmpty(orderDetailList)) {
            for (OrderDetail orderDetail : orderDetailList) {
                orderDetail.setSourceId(1L);
                if("1".equals(orderType)){
                    orderDetail.setSourceType("MALL");
                }else{
                    orderDetail.setSourceType("SECKILL");
                }
                orderDetail.setOrderId(orderId);
            }
            orderDetailService.saveBatch(orderDetailList);
        }
        return orderId;
    }


    /**
     * 渲染订单确认页面-生成用户流水号
     *
     * @param userId
     * @return
     */
    @Override
    public String generateTradeNo(String userId) {
        //1.构建流水号Key
        String userTradeKey = RedisConst.USER_KEY_PREFIX + userId + ":tradeNo";
        //2.构建流水号value
        String tradeNo = UUID.randomUUID().toString();
        //3.将流水号存入Redis 暂存5分钟
        redisTemplate.opsForValue().set(userTradeKey, tradeNo, RedisConst.SKULOCK_EXPIRE_PX1, TimeUnit.MINUTES);
        return tradeNo;
    }

    /**
     * 验证页面提交流水号是否有效
     *
     * @param userId
     * @param tradeNo
     * @return
     */
    @Override
    public Boolean checkTradeNo(String userId, String tradeNo) {
        String userTradeKey = RedisConst.USER_KEY_PREFIX + userId + ":tradeNo";
        String redisTradeNo = (String) redisTemplate.opsForValue().get(userTradeKey);
        return tradeNo.equals(redisTradeNo);
    }


    /**
     * 删除流水号
     *
     * @param userId
     */
    @Override
    public void deleteTradeNo(String userId) {
        String userTradeKey = RedisConst.USER_KEY_PREFIX + userId + ":tradeNo";
        redisTemplate.delete(userTradeKey);
    }


    /**
     * 远程调用仓库系统验证商品库存
     * Java发起Http请求：采用常用http工具包（HttpClient,UrlConnection,OkHttp,OpenFeign）
     *
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public boolean checkSkuStock(Long skuId, Integer skuNum) {
        if (skuId == null || skuNum == null) {
            throw new RuntimeException("提交参数有误");
        }
        String requestUrl = "http://localhost:9001/hasStock?num=" + skuNum + "&skuId=" + skuId;
        String hashStock = HttpClientUtil.doGet(requestUrl);
        return "1".equals(hashStock);
    }


    /**
     * 分页查询指定用户订单列表（包含订单中订单明细）
     *
     * @param infoPage
     * @param userId
     * @return
     */
    @Override
    public Page<OrderInfo> getOrderByPage(Page<OrderInfo> infoPage, String userId) {
        return baseMapper.getOrderByPage(infoPage, userId);
    }


    /**
     * 根据订单ID查询订单支付状态，如果订单状态为：未支付，将其改为关闭
     *
     * @param orderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void execCloseOrder(Long orderId) {
        //1.根据订单ID查询订单信息
        OrderInfo orderInfo = this.getById(orderId);

        //2.判断订单状态
        if (orderId != null && PaymentStatus.UNPAID.name().equals(orderInfo.getOrderStatus())) {
            this.updateOrderStatus(orderId, ProcessStatus.CLOSED);
        }
        //3.TODO 发送MQ消息通知支付系统关闭可能产生本地交易记录跟支付宝交易记录
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
    }


    /**
     * 根据订单ID将订单改为指定状态
     *
     * @param orderId
     * @param processStatus
     */
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        this.updateById(orderInfo);

    }

    /**
     * 根据订单ID查询订单及订单明细
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        //1.根据主键查询订单记录
        OrderInfo orderInfo = this.getById(orderId);
        //2.根据订单ID查询订单明细列表
        if (orderInfo != null) {
            LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OrderDetail::getOrderId, orderId);
            List<OrderDetail> orderDetailList = orderDetailService.list(queryWrapper);
            orderInfo.setOrderDetailList(orderDetailList);
            return orderInfo;
        }
        return null;
    }

    /**
     * 处理订单支付成功->修改订单状态，发送消息通知库存锁定库存
     *
     * @param orderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processPaySucess(Long orderId) {
        //1.监听到订单被支付成功后业务处理只处理一次：幂等性处理
        String key = "mq:pay:success:" + orderId;
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, orderId.toString(), 5, TimeUnit.MINUTES);
        if (!flag) {
            return;
        }
        //2.修改订单状态改为：已支付
        this.updateOrderStatus(orderId, ProcessStatus.PAID);

        //3.TODO 发送MQ消息通知库存系统锁定库存(查询文档得到库存系统所需参数-JSON字符串包含订单相关信息，订单明细集合)
        //3.1 根据订单ID查询订单及订单明细列表
        OrderInfo orderInfo = this.getOrderInfo(orderId);
        if (orderInfo != null) {
            //3.2 基于订单相关信息封装对接库存系统Map  在发送消息到MQ将Map转为JSON字符串
            Map<String, Object> mapResult = initWareMap(orderInfo);
            //3.3 发送消息到MQ异步通知库存系统进行库存锁定或拆单
            String deductMsg = JSON.toJSONString(mapResult);
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK, MqConst.ROUTING_WARE_STOCK, deductMsg);
        }
    }

    /**
     * 处理库存扣减结果-根据结果更新订单状态
     *
     * @param stockDeductStr "{"orderId":61,"status":"DEDUCTED"}"
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processStockDeductResult(String stockDeductStr) {
        //1.将字符串转为Map
        Map map = JSON.parseObject(stockDeductStr, Map.class);
        String orderId = (String) map.get("orderId");
        String status = (String) map.get("status");
        //2.获取扣减状态更新订单
        if ("DEDUCTED".equals(status)) {
            //将订单状态状态修改为：代发货
            this.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.WAITING_DELEVER);
        } else if ("OUT_OF_STOCK".equals(status)) {
            this.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.STOCK_EXCEPTION);
        }
    }


    /**
     * 提供给库存系统进行远程调用，完成订单拆单
     * 本质：将一个原始订单变成多个新订单（每个子订单中包含订单明细）
     *
     * @param orderId    需要进行拆分原始订单ID
     * @param wareSkuMap "[{"wareId":1,skuIds:[27]},{"wareId":2,skuIds:[31]}]"
     * @return
     */
    @Override
    public String orderSplit(Long orderId, String wareSkuMap) {
        //TODO 幂等性处理
        if (orderId == null || StringUtils.isEmpty(wareSkuMap)) {
            return null;
        }
        //1.根据原始订单ID查询原始订单及订单明细列表
        OrderInfo originOrderInfo = this.getOrderInfo(orderId);
        List<OrderDetail> originOrderDetailList = originOrderInfo.getOrderDetailList();

        //2.将提交的仓库跟SkuID对照关系字符串转为Map List集合<仓库ID，skuId集合>
        List<Map> skuWareMapList = JSON.parseArray(wareSkuMap, Map.class);
        if (!CollectionUtils.isEmpty(skuWareMapList)) {
            //3.循环遍历List 每遍历一次构建一个新子订单对象且找出子订单中订单明细 将新子订单、子订单明细进行保存
            List<OrderInfo> allSubOrderInfoList = skuWareMapList.stream().map(map -> {
                //3.1 获取当前订单对应出货仓库ID
                String wareId = (String) map.get("wareId");
                //3.2 当前订单中包含订单明细商品ID列表
                List<String> skuIdList = (List<String>) map.get("skuIds");
                //3.3 创建自订单对象-子订单对象中大部分属性从原始订单中拷贝获取
                OrderInfo subOrderInfo = new OrderInfo();
                BeanUtils.copyProperties(originOrderInfo, subOrderInfo);
                subOrderInfo.setWareId(wareId);
                //3.3.1 对原始订单明细进行过滤->得到当前新子订单订单明细计算总金额，订单概要
                List<OrderDetail> subOrderDetailList = originOrderDetailList.stream().filter(originOrderDetail -> {
                    return skuIdList.contains(originOrderDetail.getSkuId().toString());
                }).collect(Collectors.toList());
                subOrderInfo.setOrderDetailList(subOrderDetailList);
                subOrderInfo.sumTotalAmount();

                String newTradeBody = subOrderDetailList.stream().map(OrderDetail::getSkuName).collect(Collectors.joining(","));
                subOrderInfo.setTradeBody(newTradeBody);

                //3.3.2 设置当前子订单上级订单ID
                subOrderInfo.setParentOrderId(originOrderInfo.getId());

                //3.3.3 保存新子订单
                this.save(subOrderInfo);
                Long subOrderId = subOrderInfo.getId();

                //3.3.4 将所有子订单明细关联新子订单ID
                for (OrderDetail orderDetail : subOrderDetailList) {
                    orderDetail.setOrderId(subOrderId);
                }
                orderDetailService.saveBatch(subOrderDetailList);
                subOrderInfo.setOrderDetailList(subOrderDetailList);
                return subOrderInfo;
            }).collect(Collectors.toList());
            //4.将原始订单状态改为已拆分（前端页面不需要展示原始订单）
            originOrderInfo.setOrderStatus(OrderStatus.SPLIT.name());
            this.updateById(originOrderInfo);

            //5.响应业务数据返回库存系统-封装库存系统所需参数
            List<Map<String, Object>> collect = allSubOrderInfoList.stream().map(subOrderInfo -> {
                Map<String, Object> map = initWareMap(subOrderInfo);
                return map;
            }).collect(Collectors.toList());
            return JSON.toJSONString(collect);
        }
        return null;
    }


    /**
     * 保存秒杀订单
     *
     * @param orderInfo
     * @return
     */
    @Override
    public Long submitSeckillOrder(OrderInfo orderInfo) {
        //1.根据订单编号（秒杀订单编号）查询订单记录
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderInfo::getOutTradeNo, orderInfo.getOutTradeNo());
        int count = this.count(queryWrapper);
        if (count == 0) {
            //2.如果订单不存在则新增秒杀订单
            Long orderId = this.saveOrderInfo(orderInfo, "2");
            return orderId;
        }
        return null;
    }


    /**
     * 基于订单相关信息，封装库存系统所需参数
     *
     * @param orderInfo
     * @return
     */
    private Map<String, Object> initWareMap(OrderInfo orderInfo) {
        Map<String, Object> mapResult = new HashMap<>();
        //1.封装订单相关信息-7项数据
        mapResult.put("orderId", orderInfo.getId());
        mapResult.put("consignee", orderInfo.getConsignee());
        mapResult.put("consigneeTel", orderInfo.getConsigneeTel());
        mapResult.put("orderComment", orderInfo.getOrderComment());
        mapResult.put("orderBody", orderInfo.getTradeBody());
        mapResult.put("deliveryAddress", orderInfo.getDeliveryAddress());
        mapResult.put("paymentWay", PaymentWay.ONLINE.name().equals(orderInfo.getPaymentWay()) ? "1" : "2");

        //拆单业务中必须要设置订单对应出货仓库ID
        if (!StringUtils.isEmpty(orderInfo.getWareId())) {
            mapResult.put("wareId", orderInfo.getWareId());
        }

        //2.封装订单明细列表-3项数据
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if (!CollectionUtils.isEmpty(orderDetailList)) {
            //2.1 采用Stream流将集合泛型从OrderDetail转变为Map
            List<Map<String, Object>> orderDetails = orderDetailList.stream().map(orderDetail -> {
                Map<String, Object> orderDetailMap = new HashMap<>();
                orderDetailMap.put("skuId", orderDetail.getSkuId());
                orderDetailMap.put("skuNum", orderDetail.getSkuNum());
                orderDetailMap.put("skuName", orderDetail.getSkuName());
                return orderDetailMap;
            }).collect(Collectors.toList());
            mapResult.put("details", orderDetails);
        }
        return mapResult;
    }
}
